package scooper.cn.sc_base;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
 * 时间操作工具类
 * Created by jiangwj on 2014/7/30.
 */
public final class DateUtils {

    public static final long ONE_SECOND = 1000;
    public static final long ONE_MINUTE = 60 * 1000;
    /** 15m **/
    public static final long MINUTE_15  = 15 * ONE_MINUTE;
    public static final long HALF_HOUR  = 30 * ONE_MINUTE;
    public static final long ONE_HOUR   = 60 * ONE_MINUTE;
    public static final long ONE_DAY    = 24 * ONE_HOUR;
    public static final long ONE_WEEK   =  7 * ONE_DAY;

    private static final SimpleDateFormat SDF_TIME_MILLIS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINA);
    private static final SimpleDateFormat SDF_YMDHMS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    private static final SimpleDateFormat SDF_YMDHMS_2 = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);

    private static final SimpleDateFormat SDF_YMDHM = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
    private static final SimpleDateFormat SDF_YMDHM2 = new SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.CHINA);
    private static final SimpleDateFormat SDF_DATE = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
    private static final SimpleDateFormat SDF_MDHM = new SimpleDateFormat("MM-dd HH:mm", Locale.CHINA);
    private static final SimpleDateFormat SDF_YMD = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
    private static final SimpleDateFormat SDF_MD = new SimpleDateFormat("MM-dd", Locale.CHINA);
    private static final SimpleDateFormat SDF_HM = new SimpleDateFormat("HH:mm", Locale.CHINA);

    private static final SimpleDateFormat SDF_YEAR = new SimpleDateFormat("yyyy", Locale.CHINA);
    private static final SimpleDateFormat SDF_WEEK = new SimpleDateFormat("E HH:mm", Locale.CHINA);
    private static final SimpleDateFormat SDF_WEEK_DATE = new SimpleDateFormat("E", Locale.CHINA);

    public static final SimpleDateFormat DURATION_MINUTE_FMT = new SimpleDateFormat("mm:ss", Locale.CHINA);
    public static final SimpleDateFormat DURATION_HOUR_FMT = new SimpleDateFormat("HH:mm:ss", Locale.CHINA);

    /**
     * 返回指定日期的 00:00:00
     * @param date
     * @return
     */
    public static Date dayBegin(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE     , 0);
        cal.set(Calendar.SECOND     , 0);
        cal.set(Calendar.MILLISECOND, 0);
        //
        return cal.getTime();
    }

    /**
     * 返回指定日期的 23:59:59.999
     * @param date
     * @return
     */
    public static Date dayEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE     , 59);
        cal.set(Calendar.SECOND     , 59);
        cal.set(Calendar.MILLISECOND, 999);
        //
        return cal.getTime();
    }


    /**
     * 获取当前系统时间
     * @return
     */
    public static Date now() {
        return new Date(System.currentTimeMillis());
    }

    /**
     * 根据时间新建日期对象
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static Date newDate(int year, int month, int day) {
        return newDate(year, month, day, 0, 0, 0, 0);
    }

    /**
     * 根据时间新建日期对象
     * @param year
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @return
     */
    public static Date newDate(int year, int month, int day, int hour, int minute) {
        return newDate(year, month, day, hour, minute, 0, 0);
    }

    /**
     * 根据时间新建日期对象
     * @param year
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    public static Date newDate(int year, int month, int day, int hour, int minute, int second) {
        return newDate(year, month, day, hour, minute, second, 0);
    }

    /**
     * 根据时间新建日期对象
     * @param year
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @param millisecond
     * @return
     */
    public static Date newDate(int year, int month, int day, int hour, int minute, int second, int millisecond) {
        Calendar c = Calendar.getInstance();
        c.set(year, month - 1, day, hour, minute, second);
        c.set(Calendar.MILLISECOND, millisecond);
        return c.getTime();
    }

    /**
     * 根据所给时间，加上一段时间（日期）
     * @param date
     * @param day
     * @return
     */
    public static Date addDay(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, day);
        return c.getTime();
    }

    /**
     * 根据所给的时间，加上一段时间（小时、分钟）
     * @param date
     * @param hour
     * @param minute
     * @return
     */
    public static Date addHourMinute(Date date, int hour, int minute) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.HOUR_OF_DAY, hour);
        c.add(Calendar.MINUTE, minute);
        return c.getTime();
    }

    /**
     * 根据{dateFormat}解析时间字符串
     * @param dateFormat 时间格式化类
     * @param timeStr 时间字符串
     * @return 解析后时间
     */
    public static Date timeParser(DateFormat dateFormat, String timeStr) {
        try {
            return dateFormat.parse(timeStr);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 根据{dateFormat}格式化时刻
     * @param dateFormat 时间格式化类
     * @param date 具体时刻
     * @return 格式化后字符串
     */
    public static String timeFormat(DateFormat dateFormat, Date date) {
        try {
            return dateFormat.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 解析带毫秒的时间字符串
     * @param timeStr 时间字符串
     */
    public static Date parserTimeMillisec(String timeStr) {
        return timeParser(SDF_TIME_MILLIS, timeStr);
    }

    /**
     * 格式化带毫秒的时间
     * @param date 时间
     */
    public static String formatTimeMillisec(Date date) {
        return timeFormat(SDF_TIME_MILLIS, date);
    }

    public static Date parserTimeSecond(String dateStr) {
        return timeParser(SDF_YMDHMS, dateStr);
    }


    public static String formatTimeSecond(Date date) {
        return timeFormat(SDF_YMDHMS, date);
    }

    /**
     * 当前时间
     * @return  yyyyMMddHHmmss
     */
    public static String currTimeS2() {
        return SDF_YMDHMS_2.format(new Date());
    }

    public static String formatDetail2(Date date) {
        return SDF_YMDHM.format(date);
    }

    public static String formatDay(Date date) {
        return SDF_DATE.format(date);
    }

    public static String formatHourMin(Date date) {
        return SDF_HM.format(date);
    }

    public static String reckonByTime(long time) {
        if (time < 0) {
            time = 0;
        }
        long hour = time / ONE_HOUR;
        long minute = (time - hour * ONE_HOUR) / ONE_MINUTE;
        long second = (time - hour * ONE_HOUR - minute * ONE_MINUTE) / ONE_SECOND;
        if (hour < 1) {
            return (minute > 9 ? "" : "0") + minute + ":" + (second > 9 ? "" : "0") + second;
        }
        return (hour > 9 ? "" : "0") + hour + ":" + (minute > 9 ? "" : "0") + minute + ":" + (second > 9 ? "" : "0") + second;
    }

    public static String convertTimeString(Date time) {
        if (time == null) {
            return "";
        }
        if (isSameDay(time)) {
            return SDF_HM.format(time);
        }
        if (isYesterday(time)) {
            return "昨天 " + SDF_HM.format(time);
        } else if (isTheDayBeforYesterday(time)) {
            return "前天 " + SDF_HM.format(time);
        } else if (isSameYear(time)) {
            return SDF_MDHM.format(time);
        } else {
            return SDF_YMDHM.format(time);
        }
    }

    public static String convertTimeString2(Date time) {
        if (time == null) {
            return "";
        }
        if (isSameDay(time)) {
            return SDF_HM.format(time);
        }
        if (time.after(getMondayOFWeek())) {
            return SDF_WEEK_DATE.format(time);
        } else if (isSameYear(time)) {
            return SDF_MDHM.format(time);
        } else {
            return SDF_YMDHM2.format(time);
        }
    }

    public static String convertDateString(Date time) {
        if (time == null) {
            return "";
        }
        if (isSameDay(time)) {
            return "今天";
        }
        if (time.after(getMondayOFWeek())) {
            return SDF_WEEK.format(time);
        } else if (isSameYear(time)) {
            return SDF_MD.format(time);
        } else {
            return SDF_YMD.format(time);
        }
    }

    public static boolean isSameDay(Date day1) {
        Date currentDate = new Date();
        String ds1 = SDF_DATE.format(day1);
        String ds2 = SDF_DATE.format(currentDate);
        return ds1.equals(ds2);
    }

    public static boolean isSameYear(Date year) {
        Date currentDate = new Date();
        String ds1 = SDF_YEAR.format(year);
        String ds2 = SDF_YEAR.format(currentDate);
        if (ds1.equals(ds2)) {
            return true;
        } else {
            return false;
        }
    }

    private static boolean isYesterday(Date day) {
        Calendar yesterdayCal = Calendar.getInstance(Locale.CHINA);
        yesterdayCal.add(Calendar.DATE, -1);
        String ds1 = SDF_DATE.format(day);
        String ds2 = SDF_DATE.format(yesterdayCal.getTime());
        return ds1.equals(ds2);
    }

    private static boolean isTheDayBeforYesterday(Date day) {
        Calendar yesterdayCal = Calendar.getInstance(Locale.CHINA);
        yesterdayCal.add(Calendar.DATE, -2);
        String ds1 = SDF_DATE.format(day);
        String ds2 = SDF_DATE.format(yesterdayCal.getTime());
        return ds1.equals(ds2);
    }

    public static Date getMondayOFWeek() {
        // weeks = 0;
        int mondayPlus = getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus);
        Date monday = currentDate.getTime();
        return monday;
    }

    private static int getMondayPlus() {
        Calendar cd = Calendar.getInstance();
        // 获得今天是一周的第几天，星期日是第一天，星期二是第二天......
        int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK) - 1; //因为按中国礼拜一作为第一天所以这里减1
        if (dayOfWeek == 1) {
            return 0;
        } else {
            return 1 - dayOfWeek;
        }
    }

}
